package com.etc.shiro;

import com.etc.jwt.JwtToken;
import com.etc.jwt.JwtUtil;
import com.etc.shiro.model.AuthMst;
import com.etc.shiro.model.RoleMst;
import com.etc.shiro.model.UserMst;
import com.etc.shiro.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class JWTShiroRealm extends AuthorizingRealm {
    //    private static Logger log = LoggerFactory.getLogger(EnceladusShiroRealm.class);
    @Autowired
    private UserService userService;

    /**
     * 必须重写此方法，不然Shiro会报错
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken || token instanceof UsernamePasswordToken;
    }

    // za授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = (String) principals.getPrimaryPrincipal();

        UserMst user = userService.findUserByName(username);

        for (RoleMst role : user.getRlist()) {
            authorizationInfo.addRole(role.getRname());
            for (AuthMst permission : role.getPlist()) {
                authorizationInfo.addStringPermission(permission.getAuth());
            }
        }
        return authorizationInfo;
    }

    /**
     * 鉴权
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {

        log.debug("JWTShiroRealm@doGetAuthenticationInfo");
        if (auth instanceof UsernamePasswordToken) {
            String username = (String) auth.getPrincipal();
            UserMst user = userService.findUserByName(username);
            if (user == null) {
//            return null;
                throw new UnknownAccountException();
            }

            //返回安全数据
            // input --->  TOM  __DB__ TOM/密码/salt
            // 验证     tom----密码  ---salt是否一致
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUname(), user.getPassword(),
                    ByteSource.Util.bytes(user.getCredentialsSalt()), "EnceladusShiroRealm");

            // 权限信息
            return authenticationInfo;
        } else {
            JwtToken jwt = ((JwtToken) auth);
            String token = jwt.getJsonWebToken();
            // 解密获得username，用于和数据库进行对比
            String username = null;
            try {
                //这里工具类没有处理空指针等异常这里处理一下(这里处理科学一些)
                username = JwtUtil.getUsername(token);


            } catch (Exception e) {
                throw new AuthenticationException("heard的token拼写错误或者值为空");
            }

            if (username == null) {
                log.error("token无效(空''或者null都不行!)");
                throw new AuthenticationException("token无效");
            }
            UserMst user = userService.findUserByName(username);

            if (user == null) {
                log.error("用户不存在!)");
                throw new AuthenticationException("用户不存在!");
            }
            if (!JwtUtil.verify(token, user.getUname(), user.getPassword())) {
                log.error("用户名或密码错误(token无效或者与登录者不匹配)!)");
                throw new AuthenticationException("用户名或密码错误(token无效或者与登录者不匹配)!");
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUname(), token,
                  "jwt");

            // 权限信息
            return authenticationInfo;
        }
    }
}
